package com.whfc.emp.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.common.enums.*;
import com.whfc.common.exception.BizException;
import com.whfc.common.file.FileHandler;
import com.whfc.common.file.FilePathConfig;
import com.whfc.common.file.properties.FileExpirationRules;
import com.whfc.common.geometry.Point;
import com.whfc.common.idcard.AdvancedInfo;
import com.whfc.common.idcard.IDCardUtil;
import com.whfc.common.idcard.IdentifyDTO;
import com.whfc.common.idcard.IdentifyUtil;
import com.whfc.common.result.PageData;
import com.whfc.common.result.PageVO;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.*;
import com.whfc.emp.constant.RealNamePlatformConstant;
import com.whfc.emp.dao.*;
import com.whfc.emp.dto.*;
import com.whfc.emp.dto.openapi.OpenApiEmpDTO;
import com.whfc.emp.entity.*;
import com.whfc.emp.enums.NetState;
import com.whfc.emp.enums.*;
import com.whfc.emp.manager.AppEmpDataManager;
import com.whfc.emp.manager.AppFaceGateManager;
import com.whfc.emp.manager.CommonEmpConfigManager;
import com.whfc.emp.manager.FaceBaiDuManager;
import com.whfc.emp.param.*;
import com.whfc.emp.realNamePlatform.jingZhou.JINGZHOUApi;
import com.whfc.emp.realNamePlatform.jingZhou.model.ProjectWorkerDTO;
import com.whfc.emp.realNamePlatform.jingZhou.model.WorkerEntryExitDTO;
import com.whfc.emp.realNamePlatform.jingZhou.util.AesUtils;
import com.whfc.emp.redis.IdCardIdentifyRedisDao;
import com.whfc.emp.service.AppEmpService;
import com.whfc.entity.dto.OssPathDTO;
import com.whfc.fuum.dto.AppCorpDTO;
import com.whfc.fuum.dto.AppProjectDTO;
import com.whfc.fuum.dto.SysDeptDTO;
import com.whfc.fuum.entity.SysEmpUser;
import com.whfc.fuum.service.AppCorpService;
import com.whfc.fuum.service.AppProjectService;
import com.whfc.fuum.service.SysDeptService;
import com.whfc.fuum.service.SysUserService;
import com.whfc.hdc.dto.AppDeviceDTO;
import com.whfc.hdc.service.AppDeviceService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @ClasssName AppEmpServiceImpl
 * @Description 人员管理
 * @Author hw
 * @Date 2020/12/28 10:08
 * @Version 1.0
 */
@DubboService(interfaceClass = AppEmpService.class, version = "1.0.0", timeout = 30 * 1000)
public class AppEmpServiceImpl implements AppEmpService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @DubboReference(interfaceClass = AppDeviceService.class, version = "1.0.0")
    private AppDeviceService commonDeviceService;

    @DubboReference(interfaceClass = AppProjectService.class, version = "1.0.0")
    private AppProjectService appProjectService;

    @DubboReference(interfaceClass = SysDeptService.class, version = "1.0.0")
    private SysDeptService sysDeptService;

    @DubboReference(interfaceClass = AppCorpService.class, version = "1.0.0")
    private AppCorpService appCorpService;

    @DubboReference(interfaceClass = SysUserService.class, version = "1.0.0")
    private SysUserService sysUserService;

    @Autowired
    private AppEmpMapper appEmpMapper;

    @Autowired
    private AppEmpGroupMapper appEmpGroupMapper;

    @Autowired
    private AppEmpWorkTypeMapper appEmpWorkTypeMapper;

    @Autowired
    private AppEmpDataMapper appEmpDataMapper;

    @Autowired
    private AppEmpEnterRecordMapper appEmpEnterRecordMapper;

    @Autowired
    private AppEmpBankMapper appEmpBankMapper;

    @Autowired
    private AppEmpBlackListMapper appEmpBlackListMapper;

    @Autowired
    private AppEmpDeviceMapper appEmpDeviceMapper;

    @Autowired
    private AppEmpDeviceLogMapper appEmpDeviceLogMapper;

    @Autowired
    private AppEmpCertMapper appEmpCertMapper;

    @Autowired
    private AppEmpCertAttachMapper appEmpCertAttachMapper;

    @Autowired
    private CommonEmpConfigManager commonEmpConfigManager;

    @Autowired
    private AppEmpDataManager appEmpDataManager;

    @Autowired
    private AppEmpAttendRecordMapper appEmpAttendRecordMapper;

    @Autowired
    private AppEmpDayMapper appEmpDayMapper;

    @Autowired
    private AppEmpApplyMapper appEmpApplyMapper;

    @Autowired
    private AppFaceGateManager appFaceGateManager;

    @Autowired
    private IdCardIdentifyRedisDao idCardIdentifyRedisDao;

    @Autowired
    private FilePathConfig msFilePathConfig;

    @Autowired
    private FileHandler fileHandler;

    @Autowired
    private FaceBaiDuManager faceBaiDuManager;

    @Autowired
    private AppFenceMapper appFenceMapper;

    @Autowired
    private AppSyncRealNameConfigDao appSyncRealNameConfigDao;

    @Value("${emp.info.url}")
    private String empInfoUrl;

    @Value("${emp.idCardIdentify.num}")
    private Integer idCardIdentifyNum;

    @Override
    public PageData<AppEmpDTO> list(AppEmpListParam request) {
        logger.info("查询人员列表,request：{}", request);
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<AppEmpDTO> list = appEmpMapper.selectByParam(request);
        PageHelper.clearPage();
        for (AppEmpDTO appEmpDTO : list) {
            SysEmpUser empUser = sysUserService.getEmpUserByEmpId(appEmpDTO.getEmpId());
            appEmpDTO.setHasSysUserInfo(empUser != null);
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public AppEmpNumDTO empNum(AppEmpListParam request) throws BizException {
        return appEmpMapper.selectEmpNumByParam(request);
    }

    @Override
    public PageData<AppEmpDTO> listByDeptIdList(List<Integer> deptIdList, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("查询人员列表,deptIdList：{}, pageNum:{}, pageSize:{}", deptIdList, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<AppEmpDTO> list = appEmpMapper.selectByDeptIdList(deptIdList);
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public OssPathDTO export(AppEmpListExportParam param) {
        logger.info("导出人员列表：param：{}", param);
        OssPathDTO ossPathDTO = new OssPathDTO();
        try {
            AppEmpListParam request = new AppEmpListParam();
            BeanUtils.copyProperties(param, request);
            List<AppEmpDTO> list = appEmpMapper.selectByParam(request);
            // 获取模板
            ClassPathResource resource = new ClassPathResource("templates/empListTemplate.xls");
            InputStream templateFileInputStream = resource.getInputStream();
            File tempFile = FileUtil.copyTemplateFile(templateFileInputStream);

            //写数据
            FileInputStream fileInputStream = new FileInputStream(tempFile);
            HSSFWorkbook workbook = new HSSFWorkbook(fileInputStream);
            HSSFSheet sheet = workbook.getSheetAt(0);
            HSSFRow oneRow = sheet.getRow(0);
            String deptName = sysDeptService.getDeptName(request.getDeptId());

            oneRow.getCell(0).setCellValue(deptName + " " + "人员列表");
            //填充数据
            int rowIdx = 2;
            for (AppEmpDTO appEmpDTO : list) {
                HSSFRow row = sheet.createRow(rowIdx);
                String age = "";
                if (appEmpDTO.getBirthday() != null) {
                    age = String.valueOf(DateUtil.getAge(appEmpDTO.getBirthday()));
                }
                row.createCell(0).setCellValue(appEmpDTO.getEmpName());
                row.createCell(1).setCellValue(age);
                row.createCell(2).setCellValue(Gender.parseValue(appEmpDTO.getGender()));
                row.createCell(3).setCellValue(appEmpDTO.getIdCardNo());
                row.createCell(4).setCellValue(appEmpDTO.getWorkRoleName());
                row.createCell(5).setCellValue(appEmpDTO.getWorkTypeName());
                row.createCell(6).setCellValue(appEmpDTO.getGroupName());
                Date enterTime = appEmpDTO.getEnterTime();
                String enterTimeStr = "";
                if (enterTime != null) {
                    enterTimeStr = DateUtil.formatDate(enterTime, DateUtil.DATE_FORMAT);
                }
                row.createCell(7).setCellValue(enterTimeStr);
                Date outerTime = appEmpDTO.getOuterTime();
                String outerTimeStr = "";
                if (outerTime != null && PostState.OUTER.getValue().equals(appEmpDTO.getPostState())) {
                    outerTimeStr = DateUtil.formatDate(outerTime, DateUtil.DATE_FORMAT);
                }
                row.createCell(8).setCellValue(outerTimeStr);
                row.createCell(9).setCellValue(BindFlag.parseValue(appEmpDTO.getBindFlag()));
                row.createCell(10).setCellValue(PostState.parseValue(appEmpDTO.getPostState()).getDesc());
                rowIdx++;
            }

            //保存excel
            FileOutputStream fos = new FileOutputStream(tempFile);
            workbook.write(fos);
            fos.flush();
            fos.close();

            //上传oss
            String name = msFilePathConfig.getFilePath("emp/tmp", String.format("%s%s人员列表.xls", DateUtil.formatDate(new Date(), DateUtil.DATE_FORMAT), deptName));
            FileInputStream inputStream = new FileInputStream(tempFile);
            String upload = fileHandler.upload(name, inputStream, FileExpirationRules.oneDay);
            ossPathDTO.setPath(upload);
        } catch (Exception e) {
            logger.error("导出人员列表失败", e);
        }
        return ossPathDTO;
    }

    @Override
    public List<AppEmpDTO> list(Integer deptId, String empName) {
        logger.info("人员列表（不分页）,deptId：{}，empName:{}", deptId, empName);
        return appEmpMapper.selectByDeptId(deptId, empName);
    }

    @Override
    public AppEmpDTO detail(Integer empId) {
        logger.info("查看人员详情,empId:{}", empId);
        AppEmp appEmp = appEmpMapper.selectByPrimaryKey(empId);
        if (appEmp == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "未找到该人员");
        }
        AppEmpDTO appEmpDTO = new AppEmpDTO();
        BeanUtils.copyProperties(appEmp, appEmpDTO);
        Integer workTypeId = appEmp.getWorkTypeId();
        //获取工种
        AppEmpWorkType appEmpWorkType = appEmpWorkTypeMapper.selectByPrimaryKey(workTypeId);
        if (appEmpWorkType != null) {
            appEmpDTO.setWorkTypeName(appEmpWorkType.getName());
        }
        //获取人员班组
        AppEmpGroup appEmpGroup = appEmpGroupMapper.selectByPrimaryKey(appEmp.getGroupId());
        if (appEmpGroup != null) {
            appEmpDTO.setGroupName(appEmpGroup.getGroupName());
        }
        //设置三级教育状态
        appEmpDTO.setPassFlag(appEmp.getEnterTrainFlag());
        appEmpDTO.setEmpId(empId);
        return appEmpDTO;
    }

    @Override
    public AppEmpDTO getEmpInfo(Integer empId) {
        logger.info("获取人员信息,empId:{}", empId);
        AppEmpDTO empDTO = appEmpMapper.selectEmpDTOById(empId);
        if (empDTO == null) return null;
        //计算年龄
        Date birthday = empDTO.getBirthday();
        if (birthday != null) {
            int age = DateUtil.getAge(birthday);
            empDTO.setAge(age);
        }
        return empDTO;
    }

    @Override
    public OssPathDTO getEmpQr(Integer empId) {
        logger.info("生成人员二维码,empId：{}", empId);
        AppEmpDTO empDTO = getEmpInfo(empId);
        if (empDTO == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "未找到该人员信息");
        }
        String qr = empDTO.getQr();
        OssPathDTO ossPathDTO = new OssPathDTO();
        if (!StringUtils.isBlank(qr)) {
            ossPathDTO.setPath(qr);
            return ossPathDTO;
        }
        try {
            //ClassPathResource resource = new ClassPathResource("log.jpg");
            ClassPathResource resource = new ClassPathResource("120.png");
            InputStream inputStream1 = resource.getInputStream();
            String empName = empDTO.getEmpName();
            String fileName = "ags" + empId;
            File tempFile = File.createTempFile(fileName, ".jpg");
            QRCodeUtil.encode(empInfoUrl + empId, empName, inputStream1, tempFile.getAbsolutePath());

            //上传oss
            FileInputStream inputStream = new FileInputStream(tempFile);
            Map<String, String> headers = new HashMap<>();
            headers.put("cache-control", "no-cache");
            String path = msFilePathConfig.getFilePath("emp/qr", fileName, "jpg");
            String upload = fileHandler.upload(path, inputStream, headers);
            // 更新人员二维码信息
            appEmpMapper.updateQrByEmpId(empId, upload);
            ossPathDTO.setPath(upload);
        } catch (Exception e) {
            logger.info("生成人员二维码失败，", e);
        }

        return ossPathDTO;

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(AppEmpAddParam request) {
        logger.info("人员管理-添加人员,request:{}", request);
        Date birthday = request.getBirthday();
        String idCardNo = request.getIdCardNo();
        Integer projectId = request.getProjectId();
        if (StringUtils.isNotEmpty(idCardNo)) {
            birthday = IDCardUtil.getBirth(idCardNo);
            request.setBirthday(birthday);
        }

        if (birthday != null) {

            int age = DateUtil.getAge(birthday);
            Integer gender = request.getGender();
            this.checkAge(projectId, age, gender);
        }

        if (!StringUtils.isBlank(idCardNo)) {
            //人证对比
            this.idCardVerify(projectId, request.getEmpName(), idCardNo, request.getIdCardFront());
        }

        //添加人员
        Integer empId = addEmp(request);
        // 添加到人脸库
//        if (StringUtils.isNotBlank(request.getAvatarBase64()) && StringUtils.isNotBlank(request.getPhone())) {
//            org.json.JSONObject jsonObject = faceBaiDuManager.addUser(request.getAvatarBase64(), String.valueOf(projectId), String.valueOf(empId));
//            logger.info("人脸绑定结果:{}", jsonObject);
//            int code = jsonObject.getInt("error_code");
//            if (code != 0) {
//                throw new BizException(ResultEnum.FAILURE.getCode(), "人脸库录入失败");
//            }
//        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void edit(AppEmpEditParam request) {
        logger.info("人员管理-编辑人员，request:{}", request);
        Integer projectId = request.getProjectId();
        Integer deptId = request.getProjectId();
        Integer empId = request.getEmpId();
        String idCardNo = request.getIdCardNo();
        String empCode = request.getEmpCode();
        String phone = request.getPhone();
        Integer groupId = request.getGroupId();

        // 根据班组id查找合作单位
        AppEmpGroup appEmpGroup = appEmpGroupMapper.selectByPrimaryKey(groupId);
        if (appEmpGroup == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "选择的班组不存在");
        }
        String groupName = appEmpGroup.getGroupName();

        //人证对比
        if (!StringUtils.isBlank(idCardNo)) {
            this.idCardVerify(projectId, request.getEmpName(), idCardNo, request.getIdCardFront());
            Date birthday = IDCardUtil.getBirth(idCardNo);
            request.setBirthday(birthday);
        }

        //验证人员编号
        if (StringUtils.isNotEmpty(empCode)) {
            AppEmp emp = appEmpMapper.selectByDeptIdAndEmpCode(deptId, empCode);
            if (emp != null && !emp.getId().equals(empId)) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "当前项目人员编号已存在");
            }
        }

        //验证人员证件号
        if (StringUtils.isNotEmpty(idCardNo)) {
            AppEmp emp = appEmpMapper.selectByDeptIdAndIdCardNo(deptId, idCardNo);
            if (emp != null && !emp.getId().equals(empId)) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "当前项目人员证件号已存在");
            }
        }

        //验收人员手机号
        if (StringUtils.isNotEmpty(phone)) {
            AppEmp emp = appEmpMapper.selectByDeptIdAndPhone(deptId, phone);
            if (emp != null && !emp.getId().equals(empId)) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "当前项目人员手机号已存在");
            }
        }

        //更新人员数据
        AppEmp appEmp = new AppEmp();
        BeanUtils.copyProperties(request, appEmp);
        appEmp.setId(empId);
        appEmp.setDeptId(deptId);
        appEmp.setProjectId(deptId);
        appEmp.setGroupId(groupId);
        appEmp.setGroupName(groupName);
        appEmp.setCorpId(appEmpGroup.getCorpId());
        appEmp.setCorpName(appEmpGroup.getCorpName());
        appEmp.setEname(PinyinUtil.toPinyin(request.getEmpName()));
        appEmp.setIdCardStartDate(request.getIdCardStartDate());
        appEmp.setIdCardEndDate(request.getIdCardEndDate());
        appEmp.setQr(null);
        appEmpMapper.updateByPrimaryKeySelective(appEmp);

        // 添加到人脸库
//        if (StringUtils.isNotBlank(request.getAvatarBase64()) && StringUtils.isNotBlank(request.getPhone())) {
//            org.json.JSONObject jsonObject = faceBaiDuManager.addUser(request.getAvatarBase64(), String.valueOf(projectId), String.valueOf(empId));
//            int code = jsonObject.getInt("error_code");
//            if (code != 0) {
//                throw new BizException(ResultEnum.FAILURE.getCode(), "人脸库录入失败");
//            }
//        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void del(Integer empId) {
        logger.info("人员管理-删除人员,empId:{}", empId);
        AppEmp appEmp = appEmpMapper.selectByPrimaryKey(empId);
        if (appEmp != null && PostState.ENTER.getValue().equals(appEmp.getPostState())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该人员还未退场，不能删除！");
        }

        appEmpMapper.delLogicByEmpId(empId);

        // 删除银行卡信息
        appEmpBankMapper.deleteLogicByEmpId(empId);
        // 删除人脸库
        faceBaiDuManager.deleteUser(String.valueOf(appEmp.getProjectId()), String.valueOf(empId));
        AppSyncRealNameConfig appSyncRealNameConfig = appSyncRealNameConfigDao.selectByDeptIdAndPlatform(appEmp.getDeptId(), RealNamePlatformConstant.JING_ZHOU);
        if (appSyncRealNameConfig != null&&1 == appEmp.getSyncState()) {
            CompletableFuture.runAsync(() -> {
                AppEmpGroup appEmpGroup = appEmpGroupMapper.selectByPrimaryKey(appEmp.getGroupId());
                JINGZHOUApi.syncDelWorker(appEmp.getIdCardNo(), appEmpGroup.getGroupCode(), appSyncRealNameConfig);
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void enter(AppEmpEnterParam request) {
        logger.info("人员管理-人员进场：request：{}", request);
        Integer empId = request.getEmpId();
        AppEmp appEmp = appEmpMapper.selectByPrimaryKey(empId);
        if (appEmp == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该人员不存在");
        }
        this.checkBlackList(appEmp);

        appEmpMapper.updatePostState(empId, PostState.ENTER.getValue(), request.getDate());

        //向人员进出场记录表中插入数据
        AppEmpEnterRecord empEnterRecord = new AppEmpEnterRecord();
        empEnterRecord.setCorpId(appEmp.getCorpId());
        empEnterRecord.setDate(request.getDate());
        empEnterRecord.setDeptId(appEmp.getDeptId());
        empEnterRecord.setEmpId(empId);
        empEnterRecord.setType(PostState.ENTER.getValue());
        appEmpEnterRecordMapper.insertSelective(empEnterRecord);

        // 查询实名制配置
        AppSyncRealNameConfig appSyncRealNameConfig = appSyncRealNameConfigDao.selectByDeptIdAndPlatform(appEmp.getDeptId(), RealNamePlatformConstant.JING_ZHOU);
        if (appSyncRealNameConfig != null) {
            CompletableFuture.runAsync(()->{
                AppEmpGroup appEmpGroup = appEmpGroupMapper.selectByPrimaryKey(appEmp.getGroupId());
                JINGZHOUApi.syncWorkerEnter(appEmp.getIdCardNo(), appEmpGroup.getGroupCode(), appSyncRealNameConfig, "1");
            });

        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void outer(AppEmpOuterParam request) {
        logger.info("人员管理-人员退场:request:{}", request);
        Integer empId = request.getEmpId();

        Integer count = appEmpDeviceMapper.countByEmpId(empId);
        if (count > 0) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该人员有绑定硬件，不能退场！");
        }
        appEmpMapper.updatePostState(empId, PostState.OUTER.getValue(), request.getDate());

        //向人员进出场记录表中插入数据
        AppEmp appEmp = appEmpMapper.selectByPrimaryKey(empId);
        AppEmpEnterRecord empEnterRecord = new AppEmpEnterRecord();
        empEnterRecord.setCorpId(appEmp.getCorpId());
        empEnterRecord.setDate(request.getDate());
        empEnterRecord.setDeptId(appEmp.getDeptId());
        empEnterRecord.setType(PostState.OUTER.getValue());
        empEnterRecord.setEmpId(empId);
        appEmpEnterRecordMapper.insertSelective(empEnterRecord);

        // 查询实名制配置
        AppSyncRealNameConfig appSyncRealNameConfig = appSyncRealNameConfigDao.selectByDeptIdAndPlatform(appEmp.getDeptId(), RealNamePlatformConstant.JING_ZHOU);
        if (appSyncRealNameConfig != null) {
            CompletableFuture.runAsync(()->{
                AppEmpGroup appEmpGroup = appEmpGroupMapper.selectByPrimaryKey(appEmp.getGroupId());
                JINGZHOUApi.syncWorkerEnter(appEmp.getIdCardNo(), appEmpGroup.getGroupCode(), appSyncRealNameConfig, "0");
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void outer(List<Integer> empIds, Date date) throws BizException {
        logger.info("人员管理,批量离职,{},{}", empIds, date);

        //批量修改敢为状态
        appEmpMapper.updatePostStateByEmpIds(empIds, PostState.OUTER.getValue(), date);

        //插入进出场离职记录
        for (Integer empId : empIds) {
            AppEmp appEmp = appEmpMapper.selectByPrimaryKey(empId);
            AppEmpEnterRecord empEnterRecord = new AppEmpEnterRecord();
            empEnterRecord.setCorpId(appEmp.getCorpId());
            empEnterRecord.setDate(date);
            empEnterRecord.setDeptId(appEmp.getDeptId());
            empEnterRecord.setType(PostState.OUTER.getValue());
            empEnterRecord.setEmpId(empId);
            appEmpEnterRecordMapper.insertSelective(empEnterRecord);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bind(String userName, Integer userId, AppEmpDeviceBindParam request) {
        logger.info("人员管理-人员绑定安全帽：userName：{}，userId：{}，request：{}", userId, userId, request);
        String sn = request.getSn();
        Integer empId = request.getEmpId();

        AppEmp appEmp = appEmpMapper.selectByPrimaryKey(empId);
        if (appEmp == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "人员不存在！");
        }

        if (appEmp.getPostState().equals(PostState.OUTER.getValue())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "人员不在岗，不能绑定！");
        }

        // 根据sn查找deviceId
        AppDeviceDTO deviceDTO = commonDeviceService.getDeviceBySn(sn);
        if (deviceDTO == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "未找到该硬件");
        }
        if (!DeviceType.helmet.getValue().equals(deviceDTO.getType()) && !DeviceType.videoHelmet.getValue().equals(deviceDTO.getType())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "只支持绑定安全帽硬件");
        }
        // 查找该硬件的绑定状态
        Integer deviceId = deviceDTO.getId();
        boolean isBind = isDeviceBind(deviceId);
        if (isBind) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该硬件已经绑定");
        }
        String color = deviceDTO.getColor();
        //人员和硬件绑定关系
        bindEmpDevice(userId, userName, empId, deviceId, sn, color);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unbind(String userName, Integer userId, AppEmpDeviceUnbindParam request) {
        logger.info("人员管理-人员解除绑定安全帽：userName：{}，userId：{}，request：{}", userId, userId, request);
        Integer empId = request.getEmpId();
        unbindEmpDevice(userId, userName, empId);
    }

    @Override
    public List<AppEmpGpsDTO> getGpsList(Integer empId, Date date) {
        logger.info("查询人员轨迹,empId:{},date:{}", empId, date);
        Date startTime = DateUtil.getDateBegin(date);
        Date endTime = DateUtil.getDateEnd(date);
        List<AppDeviceCardLog> logList = appEmpDataManager.getHelmetDataLogByEmpId(empId, date, startTime, endTime);
        return logList.stream().filter(log -> PositionUtil.isInChina(log.getLng(), log.getLat())).map(this::toGps).collect(Collectors.toList());
    }

    @Override
    public List<AppEmpCertDTO> certList(Integer empId) {
        logger.info("人员证书列表,empId:{}", empId);
        List<AppEmpCertDTO> list = appEmpCertMapper.selectByEmpId(empId);
        for (AppEmpCertDTO empCertDTO : list) {
            Integer certId = empCertDTO.getCertId();
            List<AppAttachDTO> attachList = appEmpCertAttachMapper.selectByCertId(certId);
            empCertDTO.setFileAttachList(attachList);
            empCertDTO.setFileNo(attachList.size());
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addCert(AppEmpCertAddParam request) {
        logger.info("添加证书:request:{}", request);
        // 根据证书编号去重
        String certCode = request.getCertCode();
        AppEmpCert appEmpCert = appEmpCertMapper.selectByCertCode(certCode);
        if (appEmpCert != null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该证书已存在，不能重复添加");
        }
        // 插入证书
        AppEmpCert cert = new AppEmpCert();
        BeanUtils.copyProperties(request, cert);
        appEmpCertMapper.insertSelective(cert);
        Integer certId = cert.getId();
        // 插入证书附件
        List<AppAttachDTO> fileAttachList = request.getFileAttachList();
        if (fileAttachList != null && fileAttachList.size() > 0) {
            List<AppEmpCertAttach> list = new ArrayList<>();
            for (AppAttachDTO appEmpCertAttachDTO : fileAttachList) {
                AppEmpCertAttach certAttach = new AppEmpCertAttach();
                certAttach.setCertId(certId);
                certAttach.setName(appEmpCertAttachDTO.getName());
                certAttach.setUrl(appEmpCertAttachDTO.getUrl());
                list.add(certAttach);
            }
            appEmpCertAttachMapper.batchInsert(list);
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editCert(AppEmpCertEditParam request) {
        logger.info("编辑证书,request：{}", JSONObject.toJSONString(request));
        Integer certId = request.getCertId();
        // 根据证书编号去重
        String certCode = request.getCertCode();
        AppEmpCert appEmpCert = appEmpCertMapper.selectByCertCode(certCode);
        if (appEmpCert != null && !appEmpCert.getId().equals(certId)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该证书已存在，不能重复");
        }
        // 编辑证书
        AppEmpCert cert = new AppEmpCert();
        BeanUtils.copyProperties(request, cert);
        appEmpCertMapper.updateByPrimaryKeySelective(cert);
        // 插入证书附件
        appEmpCertAttachMapper.deleteLogicByCertId(certId);
        List<AppAttachDTO> fileAttachList = request.getFileAttachList();
        if (fileAttachList != null && fileAttachList.size() > 0) {
            List<AppEmpCertAttach> list = new ArrayList<>();
            for (AppAttachDTO appEmpCertAttachDTO : fileAttachList) {
                AppEmpCertAttach certAttach = new AppEmpCertAttach();
                certAttach.setCertId(certId);
                certAttach.setUrl(appEmpCertAttachDTO.getUrl());
                certAttach.setName(appEmpCertAttachDTO.getName());
                list.add(certAttach);
            }
            appEmpCertAttachMapper.batchInsert(list);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delCert(Integer certId) {
        logger.info("删除人员证书:certId:{}", certId);
        // 逻辑删除证书
        appEmpCertMapper.deleteLogic(certId);
        // 逻辑删除证书附件
        appEmpCertAttachMapper.deleteLogicByCertId(certId);
    }

    @Override
    public List<WxEmpGroupDTO> getEmpList(Integer deptId, String keyword) throws BizException {
        // 查询组织机构下全部班组
        List<WxEmpGroupDTO> groupDTOS = appEmpGroupMapper.selectGroupNameByDeptId(deptId);
        // 根据条件查询全部人员
        List<AppEmpDTO> empDTOList = appEmpMapper.selectEmpByDeptIdAndKeyword(deptId, keyword);
        // 业务数据处理
        groupDTOS.forEach(wxEmpGroupDTO -> {
            Integer groupId = wxEmpGroupDTO.getGroupId();
            Integer onlineNum = 0;
            Integer enterNum = 0;
            Integer attendNum = 0;
            Integer localeNum = 0;
            Integer outLocaleNum = 0;
            Integer absentNum = 0;
            Integer bindNum = 0;
            Integer unbindNum = 0;

            List<AppEmpDTO> list = new ArrayList<>();
            for (AppEmpDTO appEmpDTO : empDTOList) {

                if (groupId.equals(appEmpDTO.getGroupId())) {
                    // 人员图标处理
                    HelmetIconDTO helmetIcon = appEmpDataManager.getHelmetIcon(appEmpDTO.getColor());
                    BeanUtils.copyProperties(helmetIcon, appEmpDTO);
                    // 在线人数
                    if (NetState.ONLINE.getValue().equals(appEmpDTO.getNetState())) {
                        onlineNum++;
                    }
                    // 在岗人数
                    enterNum++;
                    // 出勤人数
                    if (AttendState.ATTEND.getValue().equals(appEmpDTO.getAttendState())) {
                        attendNum++;
                        // 在场人数
                        if (LocaleState.IN.getValue().equals(appEmpDTO.getLocaleState())) {
                            localeNum++;
                        }
                        // 离场人数
                        if (LocaleState.OUT.getValue().equals(appEmpDTO.getLocaleState())) {
                            outLocaleNum++;
                        }
                    }
                    // 缺勤人数
                    if (AttendState.ABSENCE.getValue().equals(appEmpDTO.getAttendState())) {
                        absentNum++;
                    }
                    // 绑定人数
                    if (BindFlag.BIND.getValue().equals(appEmpDTO.getBindFlag())) {
                        bindNum++;
                    }
                    // 未绑定人数
                    if (BindFlag.UNBIND.getValue().equals(appEmpDTO.getBindFlag())) {
                        unbindNum++;
                    }

                    list.add(appEmpDTO);
                }
            }

            wxEmpGroupDTO.setOnlineNum(onlineNum);
            wxEmpGroupDTO.setEnterNum(enterNum);
            wxEmpGroupDTO.setAttendNum(attendNum);
            wxEmpGroupDTO.setLocaleNum(localeNum);
            wxEmpGroupDTO.setOutLocaleNum(outLocaleNum);
            wxEmpGroupDTO.setAbsentNum(absentNum);
            wxEmpGroupDTO.setBindNum(bindNum);
            wxEmpGroupDTO.setUnbindNum(unbindNum);
            wxEmpGroupDTO.setDataList(list);
        });

        return groupDTOS;
    }

    @Override
    public List<AppEmpDTO> getLeaderList(Integer deptId, String keyword) throws BizException {
        List<AppEmpDTO> empDTOList = appEmpMapper.selectEmpByDeptIdAndKeyword(deptId, keyword);
        empDTOList.stream().filter(appEmpDTO -> LeaderFlag.LEADER.getValue() == appEmpDTO.getLeaderFlag()).collect(Collectors.toList());
        return empDTOList;
    }

    @Override
    public WxMapEmpDTO getMapList(Integer deptId) throws BizException {

        // 查询组织机构下全部班组
        List<WxEmpGroupDTO> groupDTOS = appEmpGroupMapper.selectGroupNameByDeptId(deptId);
        // 根据条件查询全部人员
        List<AppEmpDTO> empDTOList = appEmpMapper.selectEmpByDeptIdAndKeyword(deptId, null);

        // 安全帽离线或关机时长
        AppEmpSettingDTO data = commonEmpConfigManager.getMinutes(deptId);
        Date lastTime = DateUtil.addMinutes(new Date(), -data.getMinutes());

        // 坐标有效区域
        String polygonWKT = commonEmpConfigManager.getPolygonWKT(deptId);

        // 业务数据处理
        groupDTOS.forEach(wxEmpGroupDTO -> {
            Integer groupId = wxEmpGroupDTO.getGroupId();
            Integer onlineNum = 0;

            List<AppEmpDTO> list = new ArrayList<>();
            for (AppEmpDTO empDTO : empDTOList) {
                Double lat = empDTO.getLat();
                Double lng = empDTO.getLng();
                Date gpsTime = empDTO.getTime();
                empDTO.setIconUrl(empDTO.getAvatar());
                if (gpsTime != null && gpsTime.after(lastTime) && groupId.equals(empDTO.getGroupId()) && PositionUtil.contains(FenceType.POLYGON.value(), polygonWKT, null, lat, lng)) {
                    // 人员图标处理
//                    HelmetIconDTO helmetIcon = appEmpDataManager.getHelmetIcon(empDTO.getColor());
//                    BeanUtils.copyProperties(helmetIcon, empDTO);
                    // 在线人数
                    onlineNum++;
                    list.add(empDTO);
                }
            }

            wxEmpGroupDTO.setDataList(list);
            wxEmpGroupDTO.setOnlineNum(onlineNum);
        });

        WxMapEmpDTO wxMapEmpDTO = new WxMapEmpDTO();
        // 查找项目坐标
        AppProjectDTO projectDTO = appProjectService.getByDeptId(deptId);
        if (projectDTO != null) {
            Point Point = new Point();
            Point.setLat(projectDTO.getLat());
            Point.setLng(projectDTO.getLng());
            wxMapEmpDTO.setPoint(Point);
        }

        groupDTOS.sort((x, y) -> y.getOnlineNum() - x.getOnlineNum());
        wxMapEmpDTO.setList(groupDTOS);
        return wxMapEmpDTO;
    }

    @Override
    public WxMapEmpDTO getMapListNew(Integer deptId, List<Integer> groupIds, List<Integer> corpIds, String name) throws BizException {

        // 查询组织机构下全部班组
        List<WxEmpGroupDTO> groupDTOS = appEmpGroupMapper.selectGroupNameByDeptId(deptId);
        // 根据条件查询全部人员
        List<AppEmpDTO> empDTOList = appEmpMapper.selectEmpByDeptIdAndKeyword(deptId, null);

        // 安全帽离线或关机时长
        AppEmpSettingDTO data = commonEmpConfigManager.getMinutes(deptId);
        Date lastTime = DateUtil.addMinutes(new Date(), -data.getMinutes());

        // 坐标有效区域
        String polygonWKT = commonEmpConfigManager.getPolygonWKT(deptId);
        boolean groupNotEmpty = CollUtil.isNotEmpty(groupIds);
        boolean corpNotEmpty = CollUtil.isNotEmpty(corpIds);
        boolean nameBlank = StrUtil.isNotBlank(name);
        // 业务数据处理
        groupDTOS.forEach(wxEmpGroupDTO -> {
            Integer groupId = wxEmpGroupDTO.getGroupId();

            if (groupNotEmpty && !groupIds.contains(groupId)) {
                wxEmpGroupDTO.setOnlineNum(0);
                return;
            }
            Integer corpId = wxEmpGroupDTO.getCorpId();
            if (corpNotEmpty && !corpIds.contains(corpId)) {
                wxEmpGroupDTO.setOnlineNum(0);
                return;
            }
            Integer onlineNum = 0;

            List<AppEmpDTO> list = new ArrayList<>();
            for (AppEmpDTO empDTO : empDTOList) {
                Double lat = empDTO.getLat();
                Double lng = empDTO.getLng();
                Date gpsTime = empDTO.getTime();
                String empName = empDTO.getEmpName();
                if (nameBlank && !empName.contains(name)) continue;
                empDTO.setIconUrl(empDTO.getAvatar());
                if (gpsTime != null && gpsTime.after(lastTime) && groupId.equals(empDTO.getGroupId()) && PositionUtil.contains(FenceType.POLYGON.value(), polygonWKT, null, lat, lng)) {
                    // 人员图标处理
//                    HelmetIconDTO helmetIcon = appEmpDataManager.getHelmetIcon(empDTO.getColor());
//                    BeanUtils.copyProperties(helmetIcon, empDTO);
                    // 在线人数
                    onlineNum++;
                    list.add(empDTO);
                }
            }

            wxEmpGroupDTO.setDataList(list);
            wxEmpGroupDTO.setOnlineNum(onlineNum);
        });

        WxMapEmpDTO wxMapEmpDTO = new WxMapEmpDTO();
        // 查找项目坐标
        AppProjectDTO projectDTO = appProjectService.getByDeptId(deptId);
        if (projectDTO != null) {
            Point Point = new Point();
            Point.setLat(projectDTO.getLat());
            Point.setLng(projectDTO.getLng());
            wxMapEmpDTO.setPoint(Point);
        }

        groupDTOS.sort((x, y) -> y.getOnlineNum() - x.getOnlineNum());
        wxMapEmpDTO.setList(groupDTOS);
        return wxMapEmpDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bindAndAddEmp(Integer userId, String userName, DeviceBindEmp request) throws BizException {
        String sn = request.getSn();
        String idCardNo = request.getIdCardNo();
        Date birthday = EmpUtil.extractBirthday(idCardNo);
        //人员信息
        AppEmpAddParam appEmp = new AppEmpAddParam();
        BeanUtils.copyProperties(request, appEmp);
        appEmp.setBirthday(birthday);
        appEmp.setPostState(PostState.ENTER.getValue());
        appEmp.setProjectId(request.getProjectId());
        appEmp.setGroupId(request.getGroupId());
        appEmp.setGroupName(request.getGroupName());
        Integer empId = addEmp(appEmp);

        // 如果硬件sn 不为空 则绑定人员硬件
        if (StringUtils.isNotBlank(sn)) {
            //校验SN
            AppDeviceDTO device = commonDeviceService.getDeviceBySn(sn);
            if (device == null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "非法SN");
            }
            if (!DeviceType.helmet.getValue().equals(device.getType())) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "只支持绑定安全帽硬件");
            }

            Integer deviceId = device.getId();
            String color = device.getColor();
            //校验设备有无绑定
            boolean isBind = isDeviceBind(deviceId);
            if (isBind) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "硬件已经被其他人绑定");
            }
            //绑定人员和硬件
            bindEmpDevice(userId, userName, empId, deviceId, sn, color);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unbindEmpDevice(Integer userId, String userName, Integer empId) {
        logger.info("人员和硬件解绑,userId:{},userName:{},empId:{}", userId, userName, empId);
        //根据empId查找绑定信息
        AppEmpDevice appEmpDevice = appEmpDeviceMapper.selectByEmpId(empId);
        if (appEmpDevice != null) {
            //删除app_emp_device中数据
            Integer deviceId = appEmpDevice.getDeviceId();
            appEmpDeviceMapper.deleteByEmpId(empId);
            //向app_emp_device_log 中插入数据
            AppEmpDeviceLog empDeviceLog = new AppEmpDeviceLog();
            empDeviceLog.setEmpId(empId);
            empDeviceLog.setDeviceId(deviceId);
            empDeviceLog.setTime(new Date());
            empDeviceLog.setType(BindFlag.UNBIND.getValue());
            empDeviceLog.setUserId(userId);
            empDeviceLog.setUserName(userName);
            appEmpDeviceLogMapper.insertSelective(empDeviceLog);

            //更新app_emp中的绑定信息
            appEmpMapper.updateBindFlagByEmpId(empId, BindFlag.UNBIND.getValue(), null, null, null);

            // 清除app_emp_data中的数据
            this.clearEmpData(empId);
        }
    }

    @Override
    public DeviceBindCheckDTO bindCheck(String sn) {
        AppDeviceDTO device = null;
        if (!StringUtils.isBlank(sn)) {
            device = commonDeviceService.getDeviceBySn(sn);
        }
        DeviceBindCheckDTO result = new DeviceBindCheckDTO();
        if (device == null) {
            result.setAvailable(0);
            result.setMsg("未找到该硬件");
            return result;
        }
        if (!DeviceType.helmet.getValue().equals(device.getType())) {
            result.setAvailable(0);
            result.setMsg("只支持绑定安全帽硬件");
            return result;
        }
        boolean isBind = isDeviceBind(device.getId());
        if (isBind) {
            result.setAvailable(0);
            result.setMsg("硬件已经被其他人绑定");
            return result;
        }

        result.setAvailable(1);
        result.setMsg("该硬件可用");
        return result;
    }

    @Override
    public WxEmpWorkHourDTO getEmpWorkHour(Integer empId, Date date) {
        double workTimes = 0D;
        List<WxEmpLocaleStateDTO> localeStateArr = new ArrayList<>();
        Integer attendState = 0;
        Integer localeState = 0;
        AppEmpDay empDay = appEmpDayMapper.selectByEmpIdAndDate(empId, date);
        if (empDay != null) {
            workTimes = empDay.getWorkTimes();
            attendState = empDay.getAttendState();
        }
        // 查找考勤方式
        AttendType attendType = commonEmpConfigManager.getAttendTypeByEmpId(empId);
        List<AppEmpAttendRecordDTO> attendRecordDTOS = appEmpAttendRecordMapper.selectByEmpIdAndDate(empId, date, null, attendType.getValue());
        for (AppEmpAttendRecordDTO empAttendRecordDTO : attendRecordDTOS) {
            Date time = empAttendRecordDTO.getTime();
            Integer state = empAttendRecordDTO.getState();
            String name = empAttendRecordDTO.getName();
            WxEmpLocaleStateDTO empLocaleStateDTO = new WxEmpLocaleStateDTO();
            empLocaleStateDTO.setLocaleState(state);
            empLocaleStateDTO.setTime(time);
            empLocaleStateDTO.setName(name);
            empLocaleStateDTO.setLng(empAttendRecordDTO.getLng());
            empLocaleStateDTO.setLat(empAttendRecordDTO.getLat());
            localeStateArr.add(empLocaleStateDTO);
        }

        AppEmpData appEmpData = appEmpDataMapper.selectByEmpId(empId);
        if (appEmpData != null) {
            localeState = appEmpData.getLocaleState();
        }

        WxEmpWorkHourDTO workHourDTO = new WxEmpWorkHourDTO();
        workHourDTO.setEmpId(empId);
        workHourDTO.setDate(date);
        workHourDTO.setWorkTimes(workTimes);
        workHourDTO.setLocaleStateArr(localeStateArr);
        workHourDTO.setAttendState(attendState);
        workHourDTO.setLocaleState(localeState);
        return workHourDTO;
    }

    @Override
    public AppEmpGpsDTO getLatestGps(Integer empId) {
        AppEmpGpsDTO appEmpGpsDTO = new AppEmpGpsDTO();
        AppEmpData appEmpData = appEmpDataMapper.selectByEmpId(empId);
        if (appEmpData != null) {
            appEmpGpsDTO.setLat(appEmpData.getLat());
            appEmpGpsDTO.setLng(appEmpData.getLng());
        }
        return appEmpGpsDTO;
    }

    @Override
    public WxEmpDataCenterDTO getEmpDataCenter(Integer deptId) {
        WxEmpDataCenterDTO wxEmpDataCenterDTO = new WxEmpDataCenterDTO();
        //获取在岗人数
        int enterEmpNum = appEmpMapper.selectPostEmpNum(Collections.singletonList(deptId));
        wxEmpDataCenterDTO.setEnterEmpNum(enterEmpNum);
        //获取过去一周的数据
        int day = 7;
        Date now = DateUtil.getDate(new Date());
        Date endDate = DateUtil.addDays(now, -1);
        Date startDate = DateUtil.addDays(now, -day);
        List<WxEmpCurveMapDayDTO> list = appEmpDayMapper.selectWxEmpCurveMapDayDTOListInDept(deptId, startDate, endDate);
        List<WxEmpDataCenterDayDTO> dayList = new ArrayList<>();
        double totalAttendTimes = 0.0D;
        for (WxEmpCurveMapDayDTO wxEmpCurveMapDayDTO : list) {
            WxEmpDataCenterDayDTO centerDayDTO = new WxEmpDataCenterDayDTO();
            Integer totalEmpNum = wxEmpCurveMapDayDTO.getTotalEmpNum();
            wxEmpDataCenterDTO.setTotalEmpNum(totalEmpNum);
            Integer attendEmpNum = wxEmpCurveMapDayDTO.getAttendEmpNum();
            Double workTimes = wxEmpCurveMapDayDTO.getWorkTimes();
            centerDayDTO.setDate(wxEmpCurveMapDayDTO.getDate());
            centerDayDTO.setAttendEmpNum(attendEmpNum);
            centerDayDTO.setAbsentEmpNum(totalEmpNum - attendEmpNum);
            double avgAttendTimes = 0.0D;
            if (totalEmpNum > 0 && workTimes > 0) {
                avgAttendTimes = MathUtil.round((workTimes / totalEmpNum), 2);
            }
            totalAttendTimes += avgAttendTimes;
            centerDayDTO.setAvgAttendTimes(avgAttendTimes);
            dayList.add(centerDayDTO);
        }

        wxEmpDataCenterDTO.setDayList(dayList);
        double avgTotalWorkTimes = 0.0D;
        if (totalAttendTimes > 0) {
            avgTotalWorkTimes = MathUtil.round((totalAttendTimes / day), 2);
        }
        wxEmpDataCenterDTO.setAvgDayWorkTimes(avgTotalWorkTimes);
        return wxEmpDataCenterDTO;
    }


    @Override
    public Integer countByWorkRole(Integer deptId, AppWorkRole appWorkRole) throws BizException {
        return appEmpMapper.countByWorkRole(deptId, appWorkRole.getValue());
    }

    @Override
    public Integer countLocaleEmpNum(Integer deptId) throws BizException {
        List<Integer> deptIdList = sysDeptService.getDescendantDeptIdList(deptId);
        return appEmpMapper.countEmpNumByLocaleState(deptIdList, LocaleState.IN.getValue());
    }

    @Override
    public Integer countEmpByCorpId(Integer corpId) {
        logger.info("根据合作单位ID查找人员数量:corpId:{}", corpId);
        if (corpId == null) {
            return 0;
        }
        return appEmpMapper.countByCorpId(corpId);
    }


    @Override
    public PageData<AppEmpApplyDTO> getApplyList(Integer deptId, Integer checkResult, Date startTime, Date endTime, Integer pageSize, Integer pageNum) throws BizException {
        logger.info("人员审批列表，depId:{},checkResult:{},startTime:{},endTime:{},pageSize:{},pageNum:{}", deptId, checkResult, startTime, endTime, pageSize, pageNum);
        PageHelper.startPage(pageNum, pageSize);
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        List<AppEmpApplyDTO> list = appEmpApplyMapper.selectByDeptId(deptId, checkResult, startTime, endTime);
        for (AppEmpApplyDTO dto : list) {
            Date birthday = dto.getBirthday();
            if (birthday != null) {
                Integer age = DateUtil.getAge(birthday);
                dto.setAge(age);
            }
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public AppEmpApplyNumDTO getApplyNum(Integer deptId, Date startTime, Date endTime) {
        if (endTime != null) {
            endTime = DateUtil.getDateEnd(endTime);
        }
        return appEmpApplyMapper.selectNumBy(deptId, startTime, endTime);
    }

    @Override
    public AppEmpApplyDTO getApplyDetail(Integer applyEmpId) throws BizException {
        logger.info("人员审批详情，applyEmpId:{}", applyEmpId);
        AppEmpApply appEmpApply = appEmpApplyMapper.selectByPrimaryKey(applyEmpId);
        AppEmpApplyDTO dto = new AppEmpApplyDTO();
        BeanUtils.copyProperties(appEmpApply, dto);
        Date birthday = appEmpApply.getBirthday();
        if (birthday != null) {
            Integer age = DateUtil.getAge(birthday);
            dto.setAge(age);
        }
        return dto;
    }

    @Override
    public void applyDel(Integer applyEmpId) throws BizException {
        logger.info("人员审批删除,applyEmpId:{}", applyEmpId);
//        AppEmpApply appEmpApply = appEmpApplyMapper.selectByPrimaryKey(applyEmpId);
//        if (VisitorState.success.getValue().equals(appEmpApply.getCheckResult())) {
//            throw new BizException(ResultEnum.FAILURE.getCode(), "已审核通过无法删除");
//        }
        appEmpApplyMapper.del(applyEmpId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkApply(AppEnpApplyCheckParam param) throws BizException {
        logger.info("人员审批，param:{}", param);
        Integer checkResult = param.getCheckResult();
        Integer empId = param.getEmpId();
        AppEmpApply appEmpApply = appEmpApplyMapper.selectByPrimaryKey(empId);
        if (!VisitorState.pending.getValue().equals(appEmpApply.getCheckResult())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "已审批过无法再次审批");
        }

        // 验证年龄
        Integer deptId = appEmpApply.getDeptId();
        Date birthday = appEmpApply.getBirthday();
        Integer gender = appEmpApply.getGender();
        int age = DateUtil.getAge(birthday);
        this.checkAge(deptId, age, gender);

        BeanUtils.copyProperties(param, appEmpApply);
        appEmpApply.setCheckName(param.getCheckName());
        appEmpApply.setCheckTime(new Date());
        appEmpApplyMapper.updateByPrimaryKeySelective(appEmpApply);
        if (VisitorState.success.getValue().equals(checkResult)) {
            AppEmpAddParam appEmpAddParam = new AppEmpAddParam();
            BeanUtils.copyProperties(appEmpApply, appEmpAddParam);
            appEmpAddParam.setDeptId(appEmpApply.getDeptId());
            appEmpAddParam.setProjectId(appEmpApply.getDeptId());
            addEmp(appEmpAddParam);
        }
    }

    @Override
    public void empApplyAdd(AppEmpAddParam param) throws BizException {
        logger.info("人员申请，param:{}", param);
        AppEmp appEmp = appEmpMapper.selectByDeptIdAndIdCardNo(param.getDeptId(), param.getIdCardNo());
        if (appEmp != null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该人员已存在，不能重复添加");
        }
        AppEmpApply appEmpApply = appEmpApplyMapper.selectByDeptIdAndIdCardNo(param.getDeptId(), param.getIdCardNo());
        if (appEmpApply != null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该人员已存在，不能重复添加");
        }
        appEmpApply = new AppEmpApply();
        BeanUtils.copyProperties(param, appEmpApply);
        appEmpApplyMapper.insertSelective(appEmpApply);
    }

    @Override
    public AppEmpIdentifyDTO idCardIdentify(String imgUrl, String sessionId) throws BizException {
        logger.info("人员身份证识别，idCardImgUrl:{}", imgUrl);
        Integer index = idCardIdentifyRedisDao.getIdCardIdentify(sessionId);
        if (index > idCardIdentifyNum) {
            logger.info("人员身份证识别,当前用户超过限制次数,{}", imgUrl);
            fileHandler.delete(imgUrl);
            throw new BizException(ResultEnum.FAILURE.getCode(), "识别次数过多！请稍后重试");
        }
        AppEmpIdentifyDTO appEmpIdentifyDTO = new AppEmpIdentifyDTO();
        IdentifyDTO identifyDTO = IdentifyUtil.identify(imgUrl, null);
        if (identifyDTO != null) {
            AdvancedInfo advancedInfo = identifyDTO.getAdvancedInfo();
            BeanUtils.copyProperties(identifyDTO, appEmpIdentifyDTO);
            if (advancedInfo != null) {
//                String warnInfos = advancedInfo.getWarnInfos();
//                if (StringUtils.isNotEmpty(warnInfos)) {
//                    throw new BizException(ResultEnum.FAILURE.getCode(), warnInfos);
//                }
                String base64Str = advancedInfo.getPortrait();
                if (StringUtils.isNotEmpty(base64Str)) {
                    String path = msFilePathConfig.getFilePath("emp/image", RandomUtil.getRandomFileName(), "png");
                    //base64上传
                    byte[] imageByte = ImageUtil.base64ToImage(base64Str);
                    ByteArrayInputStream inputStream = new ByteArrayInputStream(imageByte);
                    String upload = fileHandler.upload(path, inputStream);
                    appEmpIdentifyDTO.setAdvancedInfo(upload);
                }
            }
            index++;
            idCardIdentifyRedisDao.addIdCardIdentify(sessionId, index);
            return appEmpIdentifyDTO;
        }
        fileHandler.delete(imgUrl);
        throw new BizException(ResultEnum.FAILURE.getCode(), "未识别出身份证信息");
    }

    @Override
    public PageData<OpenApiEmpDTO> listOpenApiEmp(Integer deptId, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("开放平台 查询人员列表,deptId：{},pageNum:{},pageSize:{}", deptId, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<OpenApiEmpDTO> list = appEmpMapper.selectOpenApiEmpList(deptId);
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public List<OpenApiEmpDTO> listOpenApiEmp(Integer deptId) throws BizException {
        return appEmpMapper.selectOpenApiEmpList(deptId);
    }

    @Override
    public OpenApiEmpDTO getOpenApiEmpDetail(Integer empId) throws BizException {
        if (empId == null) {
            return null;
        }
        return appEmpMapper.selectOpenApiEmpDetail(empId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addEmp(AppEmpAddParam request) throws BizException {
        logger.info("人员管理-添加人员:request:{}", request);

        Integer deptId = request.getProjectId();
        Integer groupId = request.getGroupId();
        String empCode = request.getEmpCode();
        String idCardNo = request.getIdCardNo();
        String phone = request.getPhone();
        Date birthday = request.getBirthday();

        //验证班组
        AppEmpGroup appEmpGroup = appEmpGroupMapper.selectByPrimaryKey(groupId);
        if (appEmpGroup == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "选择的班组不存在");
        }
        String groupName = appEmpGroup.getGroupName();
        Integer corpId = appEmpGroup.getCorpId();
        String corpName = appEmpGroup.getCorpName();

        //验证工号
        if (StringUtils.isNotEmpty(empCode)) {
            AppEmp emp = appEmpMapper.selectByDeptIdAndEmpCode(deptId, empCode);
            if (emp != null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "当前项目人员编码已存在");
            }
        }

        //验证证件号
        if (StringUtils.isNotEmpty(idCardNo)) {
            AppEmp emp = appEmpMapper.selectByDeptIdAndIdCardNo(deptId, idCardNo);
            if (emp != null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "当前项目人员证件号已存在");
            }
            if (birthday == null) {
                birthday = IDCardUtil.getBirth(idCardNo);
                request.setBirthday(birthday);
            }
        }

        //验证手机号
        if (StringUtils.isNotEmpty(phone)) {
            AppEmp emp = appEmpMapper.selectByDeptIdAndPhone(deptId, phone);
            if (emp != null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "当前项目人员手机号已存在");
            }
        }

        //新增人员信息
        AppEmp appEmp = new AppEmp();
        BeanUtils.copyProperties(request, appEmp);
        appEmp.setDeptId(deptId);
        appEmp.setProjectId(deptId);
        appEmp.setGroupId(groupId);
        appEmp.setGroupName(groupName);
        appEmp.setCorpId(corpId);
        appEmp.setCorpName(corpName);
        appEmp.setEname(PinyinUtil.toPinyin(request.getEmpName()));
        appEmp.setBindFlag(BindFlag.UNBIND.getValue());
        appEmp.setDelFlag(DelFlag.UNDELETE.getValue());
        appEmp.setIdCardStartDate(request.getIdCardStartDate());
        appEmp.setIdCardEndDate(request.getIdCardEndDate());
        appEmpMapper.insertSelective(appEmp);
        Integer empId = appEmp.getId();

        //初始化人员数据
        AppEmpData empData = new AppEmpData();
        empData.setEmpId(empId);
        empData.setNetState(NetState.OFFLINE.getValue());
        appEmpDataMapper.insertOrUpdate(empData);

        //增加人员进场记录
        AppEmpEnterRecord empEnterRecord = new AppEmpEnterRecord();
        empEnterRecord.setDeptId(deptId);
        empEnterRecord.setEmpId(empId);
        empEnterRecord.setCorpId(corpId);
        empEnterRecord.setDate(request.getEnterTime());
        empEnterRecord.setType(PostState.ENTER.getValue());
        appEmpEnterRecordMapper.insertSelective(empEnterRecord);
        return empId;
    }


    @Override
    public PageVO<AppEmpGpsDTO> getGpsListPage(Integer empId, Date date, Integer page, Integer size) throws BizException {
        logger.info("查询人员轨迹,empId:{},date:{}", empId, date);
        Date startTime = DateUtil.getDateBegin(date);
        Date endTime = DateUtil.getDateEnd(date);
        PageVO<AppDeviceCardLog> logList = appEmpDataManager.getHelmetDataLogByEmpIdPage(empId, date, startTime, endTime, page, size);
        List<AppEmpGpsDTO> collect = logList.getList().stream().filter(log -> PositionUtil.isInChina(log.getLng(), log.getLat())).map(this::toGps).collect(Collectors.toList());
        PageVO<AppEmpGpsDTO> ret = new PageVO(collect, logList.getPageNum(), logList.getPageSize(), logList.getPages(), logList.getTotal());
        return ret;

    }

    @Override
    public void delList(List<Integer> empIdList) throws BizException {
        for (Integer integer : empIdList) {
            this.del(integer);
        }
    }

    @Override
    public AppEmp selectByDeptIdAndIdCardNo(int deptId, String idCard) {
        return appEmpMapper.selectByDeptIdAndIdCardNo(deptId, idCard);
    }

    @Override
    public void updateById(AppEmp appEmp) {
        appEmpMapper.updateByPrimaryKeySelective(appEmp);
    }

    @Override
    public void attendanceSave(EmpAttendSyncDataParam empAttendSyncDataParam) {
        logger.info("九象考勤记录同步,dataParam:{}", empAttendSyncDataParam);
        appFaceGateManager.handleRec(empAttendSyncDataParam);
    }

    @Override
    public List<String> checkGps(Double lng, Double lat, Integer deptId) throws BizException {
        return appFenceMapper.checkGps(lng, lat, deptId);
    }

    @Override
    public List<AppEmpDTO> getListByPhone(String phone) {
        List<AppEmpDTO> listByPhone = appEmpMapper.getListByPhone(phone);
        if (listByPhone.size() > 0) {
            List<Integer> deptIds = listByPhone.stream().map(AppEmpDTO::getDeptId).collect(Collectors.toList());
            List<SysDeptDTO> list = sysDeptService.getDeptByIds(deptIds);
            Map<Integer, String> map = list.stream().collect(Collectors.toMap(SysDeptDTO::getId, SysDeptDTO::getName));
            for (AppEmpDTO appEmpDTO : listByPhone) {
                appEmpDTO.setDeptName(map.get(appEmpDTO.getDeptId()));
            }
        }
        return listByPhone;
    }

    @Override
    public boolean checkVideoHelmet(String sn) {
        if (StringUtils.isBlank(sn)) {
            return false;
        }

        AppDeviceDTO deviceBySnAndType = commonDeviceService.getDeviceBySnAndType(sn, DeviceType.videoHelmet.value());
        if (deviceBySnAndType == null) {
            return false;
        }
        return true;
    }

    @Override
    public void syncWorker(AppEmpEditParam request) {
        AppEmp appEmp = appEmpMapper.selectByPrimaryKey(request.getEmpId());
        AppSyncRealNameConfig appSyncRealNameConfig = appSyncRealNameConfigDao.selectByDeptIdAndPlatform(appEmp.getDeptId(), RealNamePlatformConstant.JING_ZHOU);
        if (appSyncRealNameConfig != null) {
            AppEmpGroup appEmpGroup = appEmpGroupMapper.selectByPrimaryKey(appEmp.getGroupId());
            AppEmpEnterRecord empEnterRecord = new AppEmpEnterRecord();
            empEnterRecord.setDate(appEmp.getEnterTime());
            if (0 == appEmp.getSyncState()) {
                // 同步数据荆州平台新增
                JSONObject jsonObject = JINGZHOUApi.syncWorkerAddOrUpdate(appEmp, ImageUtil.base64EncodeAndCompress(appEmp.getAvatar(), 40), empEnterRecord, appEmpGroup, appSyncRealNameConfig, JINGZHOUApi.PROJECT_WORKER_UPLOAD);
                if (0 == jsonObject.getInteger("code")) {
                    appEmp.setSyncState(1);
                    appEmpMapper.updateByPrimaryKey(appEmp);
                }
            } else {
                // 同步数据荆州平台修改
                JINGZHOUApi.syncWorkerAddOrUpdate(appEmp, ImageUtil.base64EncodeAndCompress(appEmp.getAvatar(), 40), empEnterRecord, appEmpGroup, appSyncRealNameConfig, JINGZHOUApi.PROJECT_WORKER_UPDATE);
            }
        }
    }

    @Override
    public List<AppEmp> getEmpInfoList(List<String> ids) throws BizException {
        return appEmpMapper.getEmpInfoList(ids);
    }

    @Override
    public List<AppAttachDTO> selectByEmpIdUrl(Integer empId) {
        return appEmpCertMapper.selectByEmpIdUrl(empId);
    }


    @Override
    @Async
    public void importEmp(Integer deptId, List<AppEmpImportParam> importParamList) throws BizException {
        if (importParamList == null || importParamList.isEmpty()) {
            return;
        }
        logger.info("导入人员, deptId:{}, size:{}", deptId, importParamList.size());
        for (int i = 0; i < importParamList.size(); i++) {
            AppEmpImportParam appEmpImportParam = importParamList.get(i);
            try {
                AppEmp appEmp = new AppEmp();
                appEmp.setDeptId(deptId);
                String empName = appEmpImportParam.getEmpName();
                if (StringUtils.isBlank(empName)) {
                    logger.info("姓名为空, rowNum:{}", i);
                    continue;
                }
                appEmp.setEmpName(empName);
                //处理性别
                String sex = appEmpImportParam.getGender();
                int gender = 1;
                if (StringUtils.isNotBlank(sex) && "女".equals(sex)) {
                    gender = 2;
                }
                appEmp.setGender(gender);
                //处理民族
                String nation = appEmpImportParam.getNation();
                if (StringUtils.isNotBlank(nation)) {
                    nation = nation.replace("族", "");
                }
                appEmp.setNation(nation);
                appEmp.setAddress(appEmpImportParam.getAddress());

                // 处理工人类型
                if ("建筑工人".equals(appEmpImportParam.getWorkRoleName())) {
                    appEmp.setWorkRoleName("建筑工人");
                    appEmp.setWorkRoleId(2);
                }
                if ("管理人员".equals(appEmpImportParam.getWorkRoleName())) {
                    appEmp.setWorkRoleName("管理人员");
                    appEmp.setWorkRoleId(1);
                }

                //验证证件号
                String idCardNo = appEmpImportParam.getIdCardNo();
                if (StringUtils.isNotEmpty(idCardNo)) {
                    AppEmp emp = appEmpMapper.selectByDeptIdAndIdCardNo(deptId, idCardNo);
                    if (emp != null) {
                        logger.info("当前项目人员证件号已存在,deptId:{}, idCardNo:{}", deptId, idCardNo);
                        continue;
                    }
                    appEmp.setIdCardNo(idCardNo);
                    Date birthday = IDCardUtil.getBirth(idCardNo);
                    appEmp.setBirthday(birthday);
                }

                //验证手机号
                String phone = appEmpImportParam.getPhone();
                if (StringUtils.isNotBlank(phone)) {
                    AppEmp emp = appEmpMapper.selectByDeptIdAndPhone(deptId, phone);
                    if (emp != null) {
                        logger.info("当前人员手机号已存在,deptId:{}, phone:{}", deptId, phone);
                        continue;
                    }
                    appEmp.setPhone(phone);
                }
                //处理劳务分包单位
                String corpName = appEmpImportParam.getCorpName();
                Integer corpId = null;
                if (StringUtils.isNotBlank(corpName)) {
                    AppCorpDTO corp = appCorpService.getCorpByDeptIdAndName(deptId, corpName);
                    if (corp == null) {
                        logger.info("当前合作单位不存在,deptId:{}, corpName:{}", deptId, corpName);
                        continue;
                    }
                    corpId = corp.getCorpId();
                }
                appEmp.setCorpId(corpId);
                appEmp.setCorpName(corpName);
                //处理班组
                String groupName = appEmpImportParam.getGroupName();
                if (StringUtils.isNotBlank(groupName)) {
                    AppEmpGroup group = appEmpGroupMapper.selectByDeptIdAndName(deptId, groupName, corpId);
                    if (group == null) {
                        group = new AppEmpGroup();
                        group.setDeptId(deptId);
                        group.setGroupName(groupName);
                        group.setCorpId(corpId);
                        group.setCorpName(corpName);
                        appEmpGroupMapper.insertSelective(group);
                    }
                    appEmp.setGroupId(group.getId());
                    appEmp.setGroupName(groupName);
                }
                //处理工种
                String workTypeName = StringUtils.isBlank(appEmpImportParam.getWorkTypeName()) ? "其他" : appEmpImportParam.getWorkTypeName();
                AppEmpWorkType workType = appEmpWorkTypeMapper.selectByDeptIdAndName(deptId, workTypeName);
                if (workType == null) {
                    workType = new AppEmpWorkType();
                    workType.setDeptId(deptId);
                    workType.setName(workTypeName);
                    appEmpWorkTypeMapper.insertSelective(workType);
                }
                appEmp.setWorkTypeId(workType.getId());
                appEmp.setWorkTypeName(workTypeName);

                Date enterTime = appEmpImportParam.getEnterTime();
                if (enterTime == null) {
                    enterTime = new Date();
                }
                appEmp.setEnterTime(enterTime);
                appEmpMapper.insertSelective(appEmp);


                Integer empId = appEmp.getId();

                //初始化人员数据
                AppEmpData empData = new AppEmpData();
                empData.setEmpId(empId);
                empData.setNetState(NetState.OFFLINE.getValue());
                appEmpDataMapper.insertOrUpdate(empData);

                //增加人员进场记录
                AppEmpEnterRecord empEnterRecord = new AppEmpEnterRecord();
                empEnterRecord.setDeptId(deptId);
                empEnterRecord.setEmpId(empId);
                empEnterRecord.setCorpId(corpId);
                empEnterRecord.setDate(enterTime);
                empEnterRecord.setType(PostState.ENTER.getValue());
                appEmpEnterRecordMapper.insertSelective(empEnterRecord);
            } catch (Exception e) {
                logger.warn("导入人员失败", e);
            }
        }
    }


    /*****************************************  private   *****************************************/
    /**
     * 人证对比
     *
     * @param projectId
     * @param empName
     * @param idCardNo
     * @param idCardFront
     */
    private void idCardVerify(Integer projectId, String empName, String idCardNo, String idCardFront) {
        //判断项目是否需要人证对比
        boolean isNeedIdCardVeirfy = commonEmpConfigManager.isIdCardVerify(projectId);
        if (isNeedIdCardVeirfy) {
            boolean idCardVerifyResult = IdCardVerifyUtil.idCardVerify(empName, idCardNo, idCardFront);
            if (!idCardVerifyResult) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "人证对比不通过");
            }
        }
    }

    /**
     * 人员年龄检测
     *
     * @param deptId 项目ID
     * @param age    年龄
     * @param gender 性别
     */
    private void checkAge(Integer deptId, Integer age, Integer gender) {
        AppEmpSettingDTO setting = commonEmpConfigManager.getSetting(deptId);
        Integer childLabourAgeFlag = setting.getChildLabourAgeFlag();
        if (EnableState.ENABLED.getValue().equals(childLabourAgeFlag)) {
            if (age < setting.getChildLabourAge()) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "童工禁止添加");
            }
        }
        if (Gender.man.getValue().equals(gender)) {
            Integer maleRetireAgeFlag = setting.getMaleRetireAgeFlag();
            if (EnableState.ENABLED.getValue().equals(maleRetireAgeFlag)) {
                if (age > setting.getMaleRetireAge()) {
                    throw new BizException(ResultEnum.FAILURE.getCode(), "年龄超过男工退休年龄，不能添加");
                }
            }
        }
        if (Gender.woman.getValue().equals(gender)) {
            Integer femaleRetireAgeFlag = setting.getFemaleRetireAgeFlag();
            if (EnableState.ENABLED.getValue().equals(femaleRetireAgeFlag)) {
                if (age > setting.getFemaleRetireAge()) {
                    throw new BizException(ResultEnum.FAILURE.getCode(), "年龄超过女工退休年龄，不能添加");
                }
            }
        }
    }

    /**
     * 检测人员是否在黑名单中
     *
     * @param appEmp
     */
    private void checkBlackList(AppEmp appEmp) {
        Integer deptId = appEmp.getDeptId();
        Integer empId = appEmp.getId();
        Integer projectId = appEmp.getProjectId();
        AppEmpSettingDTO setting = commonEmpConfigManager.getSetting(projectId);
        Integer empBlackListFlag = setting.getEmpBlackListFlag();
        if (EnableState.ENABLED.getValue().equals(empBlackListFlag)) {
            Integer cnt = appEmpBlackListMapper.countByEmpIdAndDeptId(empId, deptId);
            if (cnt > 0) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "人员在黑名单中，不能入场");
            }
        }
    }

    /**
     * 清除人员动态的数据
     *
     * @param empId
     */
    private void clearEmpData(Integer empId) {
        appEmpDataMapper.deleteByEmpId(empId);

        // 向表app_emp_data中插入数据
        AppEmpData record = new AppEmpData();
        record.setEmpId(empId);
        record.setNetState(NetState.OFFLINE.getValue());
        appEmpDataMapper.insertOrUpdate(record);
    }

    /**
     * 判断安全帽是否绑定
     *
     * @param deviceId
     * @return
     */
    private boolean isDeviceBind(Integer deviceId) {
        logger.info("设备是否绑定,deviceId:{}", deviceId);
        int cnt = appEmpDeviceMapper.countByDeviceId(deviceId);
        return cnt > 0;
    }

    /**
     * 人员和硬件绑定
     *
     * @param userId
     * @param userName
     * @param empId
     * @param deviceId
     * @param sn
     */
    private void bindEmpDevice(Integer userId, String userName, Integer empId, Integer deviceId, String sn, String color) {
        logger.info("人员和硬件绑定,userId:{},userName:{},empId:{},deviceId:{},sn：{}", userId, userName, empId, deviceId, sn);
        Date now = new Date();
        //绑定 向app_emp_device中插入数据
        AppEmpDevice empDevice = new AppEmpDevice();
        empDevice.setEmpId(empId);
        empDevice.setDeviceId(deviceId);
        empDevice.setBindTime(now);
        empDevice.setBindUser(userName);
        empDevice.setDelFlag(DelFlag.UNDELETE.getValue());
        appEmpDeviceMapper.insertSelective(empDevice);

        //向app_emp_device_log中插入数据
        AppEmpDeviceLog empDeviceLog = new AppEmpDeviceLog();
        empDeviceLog.setEmpId(empId);
        empDeviceLog.setDeviceId(deviceId);
        empDeviceLog.setTime(now);
        empDeviceLog.setType(BindFlag.BIND.getValue());
        empDeviceLog.setUserId(userId);
        empDeviceLog.setUserName(userName);
        appEmpDeviceLogMapper.insertSelective(empDeviceLog);

        //更新app_emp中的绑定数据
        appEmpMapper.updateBindFlagByEmpId(empId, BindFlag.BIND.getValue(), sn, deviceId, color);
    }

    /**
     * 数据转换
     *
     * @param log
     * @return
     */
    private AppEmpGpsDTO toGps(AppDeviceCardLog log) {
        AppEmpGpsDTO gpsDTO = new AppEmpGpsDTO();
        gpsDTO.setTime(log.getTime());
        gpsDTO.setLng(log.getLng());
        gpsDTO.setLat(log.getLat());
        gpsDTO.setLocation(log.getLocation());
        return gpsDTO;
    }
}
